package com.stylefeng.guns.modular.netcar.service.impl;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.stylefeng.guns.core.model.CommonKeyValue;
import com.stylefeng.guns.core.model.Pager;
import com.stylefeng.guns.core.util.AliMsgUtils;
import com.stylefeng.guns.core.util.JwtTokenUtil;
import com.stylefeng.guns.modular.netcar.dao.OrderInfMapper;
import com.stylefeng.guns.modular.netcar.model.*;
import com.stylefeng.guns.modular.netcar.service.*;
import com.stylefeng.guns.modular.system.service.ISysSerialnumInfService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import com.baomidou.mybatisplus.toolkit.IdWorker;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;


/**

 * 订单信息 Service 实现 
 * @author sasazaixian
 * @Date 2018-10-25 18:11
 */
@Service
public class OrderInfServiceImpl extends ServiceImpl<OrderInfMapper,OrderInf> implements IOrderInfService {

    @Resource
    private OrderInfMapper orderInfMapper;
    @Autowired
    private IVehiclePriceTypeService vehiclePriceTypeService;
    @Autowired
    private IOrderLineService orderLineService;
    @Autowired
    private ILineTimeSlotService lineTimeSlotService;
    @Autowired
    private ISysSerialnumInfService sysSerialnumInfService;
    @Autowired
    private ILineDispatchPsnService lineDispatchPsnService;
    @Value("${spring.validMinuteOrder}")//#订单未付款时预留票的时间 过后自动取消
    private String validMinuteOrder;

    @Value("${spring.clientHotLine}")//#客户服务热线
    private String clientHotLine;
    /**
     * 删除订单信息
     * @param orderInf
     * @return     
     */
    @Transactional
    public int deleteOrderInf(OrderInf orderInf,String token)throws Exception{
        if(orderInf==null ){
            throw new RuntimeException("参数不全！");
        }
        List<OrderInf> list=orderInfMapper.selectListOrderInf(orderInf);
        for(OrderInf order:list){
            if(order.getCiState().equals("2")){
                throw new RuntimeException("订单不是取消状态，不能删除！");
            }
        }
        return this.orderInfMapper.deleteOrderInf(orderInf);
    }
    /**
     * 批量删除订单信息
     * @param ids 主键ID数组
     * @return 
     */
    @Transactional
    public int deleteBatchOrderInf(String[] ids,String token)throws Exception{
       for(String id :ids){
           OrderInf order=orderInfMapper.findOrderInfById(id);
           if(order!=null && order.getCiState().equals("2")){
               throw new RuntimeException("订单不是取消状态，不能删除！");
           }
       }
       return this.orderInfMapper.deleteBatchOrderInf(ids);
    }
    /**
     * 查询订单信息列表
     * @param orderInf 订单信息对象
     * @return
     */
    public List<OrderInf> selectListOrderInf(OrderInf orderInf,String token)throws Exception{
       /* if(orderInf!=null && orderInf.getDatePrice()!=null && orderInf.getDispather().equals("1")){
            //通过令牌获取当前登录人员所配置的线路
            //orderInf.setDispatherLineIds();
        }*/
        if(orderInf!=null && orderInf.getDispather()!=null && orderInf.getDispather().equals("1")){
            orderInf.setDispatherLineIds(getDispatherLineIds(token));
        }
        return  this.orderInfMapper.selectListOrderInf(orderInf);
    }
    private String getDispatherLineIds(String token)throws Exception{
        LineDispatchPsn lineDispatchPsn=new LineDispatchPsn();
        String suId=JwtTokenUtil.getClaimFromToken(token).getSubject();
        if(suId==null || suId.trim().length()==0){
            throw new RuntimeException("请登录！");
        }
        lineDispatchPsn.setSuId(suId);
        List<LineDispatchPsn> listDispatchPsn= lineDispatchPsnService.selectListLineDispatchPsn(lineDispatchPsn,token);
        String lineIds="";
        for(LineDispatchPsn en:listDispatchPsn){
            lineIds+=",'"+en.getOlId()+"'";
        }
        if(lineIds.length()>1){
            lineIds=lineIds.substring(1);
        }else{
            lineIds="''";
        }
        return lineIds;
    }
    /**
	 * 分页查询订单信息列表
     * @param pager 分页对象
     * @return
     */     
    public  Map pageListOrderInf(Pager pager,String token) throws Exception{
        Page page=new Page(pager.getPageNumber(),pager.getPageSize());
        OrderInf orderInf=(OrderInf)pager.getObj();
        if(orderInf!=null && orderInf.getDispather()!=null && orderInf.getDispather().equals("1")){
            orderInf.setDispatherLineIds(getDispatherLineIds(token));
        }
        page.setRecords(orderInfMapper.selectListOrderInf(page,orderInf));
        List<OrderInf> list = page.getRecords();
        Map mapDate = new HashMap();
        mapDate.put("rows", list);
        mapDate.put("total", page.getTotal());
        mapDate.put("page", page.getCurrent());
        mapDate.put("pageCount", page.getPages());
        return mapDate;
    }
    /**
     * 同一个事务 互斥锁查询
     * @param orderInf 订单信息对象
     * @return 
     */
    public  List<OrderInf> selectListOrderInfForUpdate(OrderInf orderInf)throws Exception{
        return  this.orderInfMapper.selectListOrderInfForUpdate(orderInf);
    }
    /**
     * 通过主键id查询的订单信息列表
     * @param id 主键id
     * @return     
     */
    public  OrderInf findOrderInfById(String id,String token)throws Exception{
        return  this.orderInfMapper.findOrderInfById(id);
    }
    /**
     * 查询锁 获取对象信息
     * @param id 主键id
     * @return
     */
    public  OrderInf findOrderInfForUpdate(String id)throws Exception{
        return  this.orderInfMapper.findOrderInfForUpdate(id);
    }
    /**
     * 查询锁 获取对象信息
     * @param qrCode 乘车码
     * @return
     */
    public  OrderInf findOrderInfByQrcodeForUpdate(String qrCode)throws Exception{
        return  this.orderInfMapper.findOrderInfByQrcodeForUpdate(qrCode);
    }

    /**
     * 新增订单信息数据
     * @param orderInf  订单信息对象
     * @param sendMsmFlg  是否给乘客发送短息
     * @return
     */
    @Transactional
    public int insertOrderInf(OrderInf orderInf,String token,boolean sendMsmFlg) throws Exception {
        if(orderInf.getOiId()==null || orderInf.getOiId().trim().length()<10){
            orderInf.setOiId(IdWorker.get32UUID());
        }
        if(orderInf.getOiCode()==null || orderInf.getOiCode().trim().length()<10){
            String dateFormatStr=new SimpleDateFormat("yyyyMMdd").format(orderInf.getCreateTime());
            orderInf.setOiCode(sysSerialnumInfService.updateSysSerialnumInf(orderInf.getOtId()+"O",dateFormatStr,6,token));
        }

        if(orderInf.getOiDistance()==null){
            throw new RuntimeException("订单信息中里程不能为空！");
        }
        //检查票数数量 并且扣除票数
        checkTicketAndDeduction(orderInf,token);

        //更新预下单截止时间 时间过后将扣除的票数恢复
        //未支付 设置支付有效期时间 过期将取消占票
        if(orderInf.getPayState()==null || orderInf.getPayState().equals("0")) {
            orderInf.setCiValidTime(new Date(new Date().getTime() + (Integer.parseInt(validMinuteOrder) * 60000)));
        }else if(orderInf.getPayState()!= null && orderInf.getPayState().equals("1")){
            if(orderInf.getPayFee()==null){
                orderInf.setPayFee(orderInf.getCiTotalPrice());
            }
            if(orderInf.getPayTime()==null){
                orderInf.setPayTime(orderInf.getCreateTime());
            }
        }
        if(orderInf.getOiPackageState()==null){
            orderInf.setOiPackageState("0");
        }
        if(orderInf.getCiState()==null){
            orderInf.setCiState("0");
        }
        if(orderInf.getOiAutoPackaged()==null){
            orderInf.setOiAutoPackaged("0");
        }
        if(orderInf.getOiNewFlg()==null){
            orderInf.setOiNewFlg("0");
        }
        if(orderInf.getOiQrcode()==null){
            orderInf.setOiQrcode(String.valueOf((int)((Math.random()*9+1)*100000)));
        }

        this.orderInfMapper.insertOrderInf(orderInf);
        if(sendMsmFlg && orderInf.getPayState()!=null && orderInf.getPayState().equals("1")){
            OrderInf selOrderInf=orderInf;
            if(selOrderInf.getCiTel().length()>10){
                SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm");
                String orderTime=sdf.format(selOrderInf.getCiSendTime());
                if(selOrderInf.getOiOrderTimeStart()!=null && selOrderInf.getOiOrderTimeEnd()!=null){
                    orderTime=sdf.format(selOrderInf.getOiOrderTimeStart())+"-"+sdf.format(selOrderInf.getOiOrderTimeEnd());
                }
                Map<String,String> hmPrms =new HashMap<String,String>();
                hmPrms.put("from", selOrderInf.getOiStartAddress());
                hmPrms.put("to",  selOrderInf.getOiEndAddress());
                hmPrms.put("time",orderTime);
                hmPrms.put("tel", clientHotLine);
                AliMsgUtils.sendSmsNotice(selOrderInf.getCiTel(),"SMS_144853288",hmPrms);
            }
        }
        return 0;
    }

    /**
     * 买票 占座
     * @param orderInf
     * @param token
     * @throws Exception
     */
    private  void checkTicketAndDeduction(OrderInf orderInf,String token)throws Exception {

        int num=orderInf.getCiNum();
        if(num<1){
            throw new RuntimeException("乘车人数必须大于等于1！");
        }
        //获取线路信息 查看是否设置了按照班次发车
       VehiclePriceType tmpVehiclePriceType=new VehiclePriceType();
       tmpVehiclePriceType.setVptCode(orderInf.getVptCode());
       List<VehiclePriceType> list=vehiclePriceTypeService.selectListVehiclePriceType(tmpVehiclePriceType,token);
       if(list==null || list.size()==0){
            throw new RuntimeException("车型未找到！");
       }
       tmpVehiclePriceType=list.get(0);
       if(tmpVehiclePriceType.getCvpSeatNum()<orderInf.getCiNum()){
           throw new RuntimeException("人数不能超过"+tmpVehiclePriceType.getCvpSeatNum()+"！");
       }
       if(orderInf.getOstId().equals("0")){//专车不用扣票
            return;
       }
       String olId=orderInf.getOlId();
       //检查预下单时间
       OrderLine oline=orderLineService.findOrderLineById(olId,token);
       if(oline==null ){
           throw new RuntimeException("未找到线路！");
       }
       Date sendDate=orderInf.getCiSendTime();
       int preSaleTime=oline.getOlPreSaleMinitue();
       long minTime=new Date().getTime()+(preSaleTime*1000*60);
       if(sendDate.getTime()<=minTime){
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
            throw new RuntimeException("亲，您只能安排"+dateFormat.format(new Date(minTime))+"以后的行程！");
       }
       //检查余票
       if(oline.getOlSendByTimer().equals("1")){
           LineTimeSlot lineTimeSlot=new LineTimeSlot();
           lineTimeSlot.setLtsDate(sendDate);
           lineTimeSlot.setOlId(olId);
           lineTimeSlot.setLtsStartTime(orderInf.getOiOrderTimeStart());
           List<LineTimeSlot> listLineTimeSlot=lineTimeSlotService.selectListLineTimeSlotForUpdate(lineTimeSlot);
           if(listLineTimeSlot!=null && listLineTimeSlot.size()>0){
                lineTimeSlot=listLineTimeSlot.get(0);
                if(lineTimeSlot.getLtsMaxNum()>0){//限制购票数量
                    if((lineTimeSlot.getLtsMaxNum()-lineTimeSlot.getLtsSaleNum())<num){
                        throw new RuntimeException("该时段预留人数不足，请修改人数或选择其他时段！");
                    }
                    lineTimeSlot.setLtsSaleNum(num);
                    lineTimeSlotService.updateLineTimeSlotSaleNum(lineTimeSlot,token);
                }
           }else{
                throw new RuntimeException("未找到匹配的班次！");
           }
       }
    }

    /**
     * 取消 恢复占用的票数
     * @param orderInf
     * @param token
     */
    private void cancelTicketSalNum(OrderInf orderInf,String token)throws Exception{
        if(orderInf.getOstId().equals("0")){//专车不用扣票
           return;
        }
        int num=orderInf.getCiNum();
        String olId=orderInf.getOlId();
        //检查预下单时间
        OrderLine oline=orderLineService.findOrderLineById(olId,token);
        if(oline==null ){
            throw new RuntimeException("未找到线路！");
        }
        Date sendDate=orderInf.getCiSendTime();
        if(oline.getOlSendByTimer().equals("1")){
            LineTimeSlot lineTimeSlot=new LineTimeSlot();
            lineTimeSlot.setLtsDate(sendDate);
            lineTimeSlot.setOlId(olId);
            lineTimeSlot.setLtsStartTime(orderInf.getOiOrderTimeStart());
            List<LineTimeSlot> listLineTimeSlot=lineTimeSlotService.selectListLineTimeSlotForUpdate(lineTimeSlot);
            if(listLineTimeSlot!=null && listLineTimeSlot.size()>0){
                lineTimeSlot=listLineTimeSlot.get(0);
                if(lineTimeSlot.getLtsSaleNum()>=num){//限制购票数量
                    lineTimeSlot.setLtsSaleNum(-1*num);
                }else{
                    lineTimeSlot.setLtsSaleNum(-1*lineTimeSlot.getLtsSaleNum());
                }
                lineTimeSlotService.updateLineTimeSlotSaleNum(lineTimeSlot,token);
            }else{
                throw new RuntimeException("未找到匹配的班次！");
            }
        }
    }
    /**
     * 更新订单信息数据
     * @param orderInf 订单信息对象
     * @return     
     */
    @Transactional
    public int updateOrderInf(OrderInf orderInf,String token) throws Exception {
        //修改状态为已支付
        if(orderInf.getPayState()!=null && orderInf.getPayState().equals("1")){
            OrderInf selOrderInf=this.findOrderInfForUpdate(orderInf.getOiId());
            if(selOrderInf==null){
                throw new RuntimeException("未找到订单！");
            }
            if(selOrderInf.getPayState().equals("0") ){
                //发送短信通知乘客下单成功
                if(selOrderInf.getCiTel().length()>10){
                    SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm");
                    String orderTime=sdf.format(selOrderInf.getCiSendTime());
                    if(selOrderInf.getOiOrderTimeStart()!=null && selOrderInf.getOiOrderTimeEnd()!=null){
                        orderTime=sdf.format(selOrderInf.getOiOrderTimeStart())+"-"+sdf.format(selOrderInf.getOiOrderTimeEnd());
                    }
                    Map<String,String> hmPrms =new HashMap<String,String>();
                    hmPrms.put("from", selOrderInf.getOiStartAddress());
                    hmPrms.put("to",  selOrderInf.getOiEndAddress());
                    hmPrms.put("time",orderTime);
                    hmPrms.put("tel", clientHotLine);
                    AliMsgUtils.sendSmsNotice(selOrderInf.getCiTel(),"SMS_144853288",hmPrms);
                }
                this.orderInfMapper.updateOrderInfPayState(orderInf);
                return 0;
            }
        }
        if(orderInf.getCiState()!=null && orderInf.getCiState().equals("2")){//取消订单
            OrderInf selOrderInf=this.findOrderInfForUpdate(orderInf.getOiId());
            if(selOrderInf==null){
                throw new RuntimeException("未找到订单！");
            }

            if(selOrderInf.getOiPackageState().equals("1") || !selOrderInf.getCiState().equals("0") ){
                throw new RuntimeException("订单已经调度或乘客不是未乘车状态，不能修改！");
            }
            //数据库数据订单状态不是取消状态，不是取消状态 取消占座 修改取消
            if(selOrderInf.getCiState()!=null && !selOrderInf.getCiState().equals("2")){
                //恢复订单的票数
                cancelTicketSalNum(selOrderInf, token);
                //更新订单状态为已经取消 并且更新站票有效时间为null
            }
            this.orderInfMapper.updateOrderInfCustomStateCancel(orderInf);
        }else if(orderInf.getCiState()!=null && orderInf.getCiState().equals("0")){//恢复取消订单
            OrderInf selOrderInf=this.findOrderInfForUpdate(orderInf.getOiId());
            if(selOrderInf==null){
                throw new RuntimeException("未找到订单！");
            }
            //将取消订单修改成正常订单
            if(selOrderInf.getCiState().equals("2")){
                //检查并且占票
                checkTicketAndDeduction(selOrderInf,token);
                orderInf.setCiValidTime(new Date(new Date().getTime() +( Integer.parseInt(validMinuteOrder)*60000)));
                orderInfMapper.updateOrderInfCustomStateRestCancel(orderInf);
            }else{
                this.orderInfMapper.updateOrderInf(orderInf);
            }
        }else{
           this.orderInfMapper.updateOrderInf(orderInf);
        }
        return 0;
    }    
    /**
     * 查询订单信息返回key-Value属性
     * @param orderInf 系统操作对象
     * @return     
     */
    public List<CommonKeyValue> optionsOrderInf(OrderInf orderInf,String token) throws Exception {
        List<OrderInf> listOrderInf=this.orderInfMapper.selectListOrderInf(orderInf);
        List<CommonKeyValue> listOptions=new ArrayList<CommonKeyValue>();
        for(OrderInf item:listOrderInf){
            CommonKeyValue opts=new CommonKeyValue();
            opts.setId(""+item.getOiId());
            opts.setValue(item.getOlName());
            listOptions.add(opts);
        }
        return listOptions;
    }

    /**
     * 乘客上车 将乘客状态变成已上车，并且更新上车时间 上车位置 上车坐标
     * @param orderInf
     * @param token
     * @return
     * @throws Exception
     */
    @Transactional
    public int updateOrderInfUp(OrderInf orderInf, String token) throws Exception {
        if(orderInf==null || orderInf.getOiId()==null || orderInf.getOiId().length()<10){
            new RuntimeException("参数不全!");
        }
        this.orderInfMapper.updateOrderInfUp(orderInf);
        return 0;
    }

    /**
     * 恢复上车 将上车时间 上车地点 上车坐标置空标
     * @param orderInf
     * @param token
     * @return
     * @throws Exception
     */
    @Transactional
    public int updateOrderInfRegainUp(OrderInf orderInf, String token) throws Exception {
        if(orderInf==null || orderInf.getOiId()==null || orderInf.getOiId().length()<10){
            new RuntimeException("参数不全!");
        }
        this.orderInfMapper.updateOrderInfRegainUp(orderInf);
        return 0;
    }

    /**
     * 乘客下车 将乘客状态变成已下车，并且更新下车时间 下车位置 下车坐标
     * @param orderInf
     * @param token
     * @return
     * @throws Exception
     */
    @Transactional
    public int updateOrderInfDown(OrderInf orderInf, String token) throws Exception {
        if(orderInf==null || orderInf.getOiId()==null || orderInf.getOiId().length()<10){
            new RuntimeException("参数不全!");
        }
        this.orderInfMapper.updateOrderInfDown(orderInf);
        return 0;
    }
    /**
     *  恢复下车 将下车时间 下车地点 下车坐标置空
     * @param orderInf
     * @param token 令牌
     * @return
     * @throws Exception
     */
    @Transactional
    public int updateOrderInfRegainDown(OrderInf orderInf, String token) throws Exception {
        if(orderInf==null || orderInf.getOiId()==null || orderInf.getOiId().length()<10){
            new RuntimeException("参数不全!");
        }
        this.orderInfMapper.updateOrderInfRegainDown(orderInf);
        return 0;
    }

    /**
     *  更新乘客状态
     * @param orderInf
     * @param token 令牌
     * @return
     * @throws Exception
     */
    @Transactional
    public int updateOrderInfCustomState(OrderInf orderInf, String token) throws Exception {
        if(orderInf==null || orderInf.getCiState()==null || orderInf.getOiId()==null || orderInf.getOiId().length()<10
                || !(orderInf.getCiState().equals("0") || orderInf.getCiState().equals("1") || orderInf.getCiState().equals("2") || orderInf.getCiState().equals("3"))){
            new RuntimeException("参数不全!");
        }
        if(orderInf.getCiState().equals("2") || orderInf.getCiState().equals("0")){
            updateOrderInf(orderInf,token);
        }
        return 0;
    }

    @Transactional
    public void scheduleClearTicket()throws Exception {
        //查询过期未付款的订单
        List<OrderInf> listOrderInf=this.orderInfMapper.selectListOrderInfForClearTicket();
        for(OrderInf item:listOrderInf){
            OrderInf orderInf=this.findOrderInfForUpdate(item.getOiId());
            if(!(orderInf.getPayState().equals("0") && orderInf.getCiState().equals("0") && orderInf.getOiPackageState().equals("0") //未打包 //未支付 //未乘车
                    && orderInf.getOstId().equals("1") //快车
                    && orderInf.getCiValidTime()!=null && orderInf.getCiValidTime().compareTo(new Date())<0)){//支付时间已过
                continue;
            }
            int num=orderInf.getCiNum();
            //取消占座
            LineTimeSlot lineTimeSlot=new LineTimeSlot();
            lineTimeSlot.setLtsDate(orderInf.getCiSendTime());
            lineTimeSlot.setOlId(orderInf.getOlId());
            lineTimeSlot.setLtsStartTime(orderInf.getOiOrderTimeStart());
            List<LineTimeSlot> listLineTimeSlot=lineTimeSlotService.selectListLineTimeSlotForUpdate(lineTimeSlot);
            if(listLineTimeSlot!=null && listLineTimeSlot.size()>0){
                lineTimeSlot=listLineTimeSlot.get(0);
                if(lineTimeSlot.getLtsSaleNum()>=num){//限制购票数量
                    lineTimeSlot.setLtsSaleNum(-1*num);
                }else{
                    lineTimeSlot.setLtsSaleNum(-1*lineTimeSlot.getLtsSaleNum());
                }
                lineTimeSlotService.updateLineTimeSlotSaleNum(lineTimeSlot,"");
            }
            //更细订单为取消状态
            this.orderInfMapper.updateOrderInfCustomStateCancel(orderInf);
        }
    }
}
